from django.db import models
from base import *
from object_models import *
from resource_models import *
from protocol_models import *

__all__ = ["CHARACTERISATION_TYPES", "Experiment", "CompositeExperiment", "ChildExperiment",
           "PostProcessing", "ClusterDetection", "ParameterSetting", "NumericParameterSetting", 
           "GenericParameterSetting", "Simulation", "AppliedPhysics", "Snapshot", "TargetObjectType",
           "TargetProcess", "ObjectCollection", "InputDataset", "Characterisation", 
           "ExperimentRepresentationObject", "ExperimentProperty"]

CHARACTERISATION_TYPES = (("nominal", "A typical value, as judged by the publisher of the snapshots."),
                          ("min", "Represents the minimum  ('possible' if a priori, 'attained' if a osteriori) value for the characterised property."),
                          ("max", "Represents the maximum  ('possible' if a priori, 'attained' if a osteriori) value for the characterised property."),
                          ("mean", "Represents the mean  ('expected' if a priori, 'attained' if a posteriori) value for the characterised property."),
                          ("stdev", "Represents the expected/attained standard deviation for the characterised property."))
      
class Experiment(Resource):
    _collection_sets = []
    protocol = models.ForeignKey(Protocol, blank=True, null=True)

class ParameterSetting(MetadataObject):
    _collection_sets = []
    experiment = models.ForeignKey(Experiment)
    inputparameter = models.ForeignKey(InputParameter)
    _container_field = "experiment_id"

    class Meta:
        abstract = True

class NumericParameterSetting(ParameterSetting):
    _collection_sets = []
    value_value = models.TextField(blank=True, null=True)
    value_unit = models.TextField(blank=True, null=True)
    Experiment._collection_sets.append('numericparametersetting_set')

class GenericParameterSetting(ParameterSetting):
    _collection_sets = []
    value = models.TextField(blank=True, null=True)
    Experiment._collection_sets.append('genericparametersetting_set')

class Snapshot(MetadataObject):
    _collection_sets = []
    experiment = models.ForeignKey(Experiment)
    publisherDID = models.CharField(max_length=1024, blank=True)
    time_value = models.CharField(max_length=1024, blank=True)
    time_unit = models.CharField(max_length=1024, blank=True)
    spatialsizephysical_value = models.CharField(max_length=1024, blank=True)
    spatialsizephysical_unit = models.CharField(max_length=1024, blank=True)
    _container_field = "experiment_id"
    Experiment._collection_sets.append('snapshot_set')

class TargetObjectType(ObjectType):
    _collection_sets = []
    experiment = models.ForeignKey(Experiment)
    multiplicity = models.CharField(max_length=256,
                                    choices=CARDINALITY, default="0..*")
    identityname = models.CharField(max_length=1024, blank=True)
    label = models.CharField(max_length=1024, blank=True)
    _container_field = "experiment_id"
    Experiment._collection_sets.append('targetobjecttype_set')

class TargetProcess(ObjectType):
    _collection_sets = []
    experiment = models.ForeignKey(Experiment)
    astrojournalsubject = models.CharField(max_length=1024, blank=True)
    _container_field = "experiment_id"
    Experiment._collection_sets.append('targetprocess_set')

class ObjectCollection(MetadataObject):
    _collection_sets = []
    snapshot = models.ForeignKey(Snapshot)
    objecttype = models.ForeignKey(ObjectType)   
    numberofobjects = models.PositiveIntegerField(default=1, blank=True, null=True)       
    _container_field = "snapshot_id"
    Snapshot._collection_sets.append('objectcollection_set')

class InputDataset(MetadataObject):
    _collection_sets = []
    experiment = models.ForeignKey(Experiment)
    snapshot = models.ForeignKey(Snapshot)
    _container_field = "experiment_id"
    Experiment._collection_sets.append('inputdataset_set')

class Characterisation(MetadataObject):
    _collection_sets = []
    objectcollection = models.ForeignKey(ObjectCollection)
    axis = models.ForeignKey(Property)
    value_value = models.CharField(max_length=1024, blank=True)
    value_unit = models.CharField(max_length=1024, blank=True)
    characterisation_type = models.CharField(max_length=256, 
                                             choices=CHARACTERISATION_TYPES,
                                             default='nominal')
    apriori = models.BooleanField(default=False)
    _container_field = "objectcollection_id"
    ObjectCollection._collection_sets.append('characterisation_set')

class ExperimentRepresentationObject(MetadataObject):
    _collection_sets = []
    experiment = models.ForeignKey(Experiment)
    representation = models.ForeignKey(RepresentationObjectType)    
    _container_field = "experiment_id"
    Experiment._collection_sets.append('experimentrepresentationobject_set')    

class ExperimentProperty(MetadataObject):
    _collection_sets = []
    experimentrepresentationobject = models.ForeignKey(ExperimentRepresentationObject)
    property = models.ForeignKey(Property)    
    _container_field = "experimentrepresentationobject_id"
    ExperimentRepresentationObject._collection_sets.append('experimentproperty_set')

class CompositeExperiment(Experiment):
    _collection_sets = []
    element_name = 'aCompositeExperiment'

class ChildExperiment(MetadataObject):
    _collection_sets = []
    compositeexperiment = models.ForeignKey(CompositeExperiment,
                                            related_name='child_experiments')
    experiment = models.ForeignKey(Experiment)
    _container_field = "compositeexperiment_id"
    CompositeExperiment._collection_sets.append('child_experiments')    

class PostProcessing(Experiment):
    _collection_sets = []
    primary_experiment = models.ForeignKey(Experiment,
                                           related_name='postprocessing_related')

class ClusterDetection(PostProcessing):
    _collection_sets = []
    element_name = 'aClusterDetection'

class Simulation(Experiment):
    _collection_sets = []
    element_name = 'aSimulation'
    executiontime = models.DateTimeField(null=True)

class AppliedPhysics(MetadataObject):
    _collection_sets = []
    simulation = models.ForeignKey(Simulation)
    physics = models.ForeignKey(Physics)
    _container_field = "simulation_id"
    Simulation._collection_sets.append('appliedphysics_set')

